/**
 * @file main.cpp
 * @author 范文宇 (2643660853@qq.com)
 * @brief 
 * @version 1.0
 * @date 2022-10-21
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include <iostream>
#include <opencv2/opencv.hpp>
#include "draw.h"
#include "graph.h"
#include "dijkstral.h"

using namespace std;
using namespace cv;


void myMouse(int event, int x, int y, int flags, void *para)
{
	if (event == EVENT_LBUTTONDOWN)
	{
		*((Point2i *)para) = Point2i(x, y);
	}
}

void myMouseON(int event, int x, int y, int flags, void *para)
{
	if (event == EVENT_LBUTTONDOWN || flags == EVENT_FLAG_LBUTTON)
	{
		*((Point2i *)para) = Point2i(x, y);
	}
}

int main(int argc, char *argv[])
{
	Graph myGraph_obj(30, 30);
	Draw myDraw_obj(myGraph_obj.getPointW(), myGraph_obj.getPointH());
	Mat img = myDraw_obj.createImg(); // 输出图像
	// 绘制图像
	myDraw_obj.DrawImg(img);
	imshow("img", img);

	// 设置障碍物
	vector<Point2i> obstaclePoint;			   // 障碍物坐标数组
	Point2i tempMousePoint = Point2i(0, 0);	   // 鼠标拖动坐标
	Point2i tempObstaclePoint = Point2i(0, 0); // 鼠标拖动点坐标
	// Point2i
	obstaclePoint.reserve(myGraph_obj.getPointW() * myGraph_obj.getPointH());
	setMouseCallback("img", myMouseON, (void *)&tempMousePoint);
	while ((char)waitKey(1) != 'q') // 摁q键确定
	{
		// 初始条件筛除
		if (obstaclePoint.size() || tempMousePoint.x != 0 || tempMousePoint.y != 0)
			tempObstaclePoint = Point2i(tempMousePoint.x / (myDraw_obj.getPointSize() + 1),
										tempMousePoint.y / (myDraw_obj.getPointSize() + 1));
		bool alreadyIn = 0; // 障碍物是否已存在
		// 查找数组确认障碍物是否已存在
		for (auto i : obstaclePoint)
		{
			if (i == tempObstaclePoint)
			{
				alreadyIn = 1;
			}
		}
		// 如果障碍物不存在
		if (!alreadyIn)
		{
			if (obstaclePoint.size() || tempObstaclePoint.x != 0 || tempObstaclePoint.y != 0)
				obstaclePoint.push_back(tempObstaclePoint);
		}
		// 储存障碍物并绘制图片
		myGraph_obj.setObstacle(obstaclePoint);
		myDraw_obj.setIfSetObstacle(1);
		myDraw_obj.DrawImg(img, &obstaclePoint, obstaclePoint.size(), myGraph_obj.getStartingPoint());
		imshow("img", img);
	}
	// 更新边距离信息
	myGraph_obj.updateEdge(obstaclePoint);

	// 设置起点
	Point2i MouseStartingPoint = Point2i(0, 0); // 鼠标坐标
	Point2i startingPoint = Point2i(0, 0);		// 鼠标点坐标
	setMouseCallback("img", myMouse, (void *)&MouseStartingPoint);
	while ((char)waitKey(1) != 'q') // 摁q键确认
	{
		startingPoint = Point2i(MouseStartingPoint.x / (myDraw_obj.getPointSize() + 1),
								MouseStartingPoint.y / (myDraw_obj.getPointSize() + 1));
		myGraph_obj.setStartingPoint(startingPoint);
		myDraw_obj.setIfSetStartingPoint(1);
		myDraw_obj.DrawImg(img, &obstaclePoint, obstaclePoint.size(), myGraph_obj.getStartingPoint());
		imshow("img", img);
	}
	cout << "start:" << startingPoint << endl;

	// 设置终点
	Point2i MouseFinishingPoint = Point2i(0, 0); // 鼠标坐标
	Point2i finishingPoint = Point2i(0, 0);		 // 鼠标点坐标
	setMouseCallback("img", myMouse, (void *)&MouseFinishingPoint);
	while ((char)waitKey(1) != 'q') // 摁q键确认
	{
		finishingPoint = Point2i(MouseFinishingPoint.x / (myDraw_obj.getPointSize() + 1),
								 MouseFinishingPoint.y / (myDraw_obj.getPointSize() + 1));
		myGraph_obj.setFinishingPoint(finishingPoint);
		myDraw_obj.setIfSetFinishingPoint(1);
		myDraw_obj.DrawImg(img, &obstaclePoint, obstaclePoint.size(), myGraph_obj.getStartingPoint(), myGraph_obj.getFinishingPoint());
		imshow("img", img);
	}
	cout << "finish:" << finishingPoint << endl;

	// 计算最短路径
	Dijkstral_ptr myAlgo_obj = make_shared<Dijkstral>(myGraph_obj.getPointW(), myGraph_obj.getPointH(),
												   myGraph_obj.getStartingPoint(),
												   myGraph_obj.getFinishingPoint(),
												   myGraph_obj.getVertex(), myGraph_obj.getEdge());
	std::vector<int> shortestPath = myAlgo_obj->getShortestPath(myGraph_obj.getPointW(),
																myGraph_obj.getPointH(),
																myGraph_obj.getStartingPoint(),
																myGraph_obj.getFinishingPoint(),
																myGraph_obj.getVertex(),
																myGraph_obj.getEdge());
	// 输出最短路径信息
	for (auto i : shortestPath)
	{
		cout << i << " ";
	}
	cout << endl;
	myDraw_obj.setIfGetPath(1);
	// 绘制路径
	myDraw_obj.DrawImg(img, &obstaclePoint, obstaclePoint.size(), myGraph_obj.getStartingPoint(),
					   myGraph_obj.getFinishingPoint(), &shortestPath, shortestPath.size());
	imshow("img", img);
	waitKey(1);
	while ((char)waitKey(1) != 'q') // 摁q键退出
	{
	}
	return 0;
}